package net.chasing.androidbaseconfig.util;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Build;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import android.view.WindowMetrics;
import android.view.inputmethod.InputMethodManager;

import androidx.activity.ComponentActivity;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.core.app.NotificationCompat;

import net.chasing.androidbaseconfig.R;
import net.chasing.androidbaseconfig.receiver.NotificationClickReceiver;
import net.chasing.androidbaseconfig.util.thread.ThreadPoolUtils;

import java.util.Stack;

/**
 * Activity工具类
 */
public class ActivityUtils {
    /**
     * 区别activityStack：在onResume进行++   onStop进行--
     * Aty生命周期：在A -> B的时候，会走B.onCreate A.onPause B.onStart B.onResume A.onStop
     * 所以一般情况StartActivityCount始终保持1
     * 回到系统桌面的时候为0
     */
    public static int StartActivityCount;
    /**
     * 因为部分功能（如启动服务、展示PopupWindow）需要等待Activity.onResume之后才能进行调用，所以进行记录resume的数量
     * 因为每次跳转界面，当前界面先进行onPause，下一个展示的才onResume，导致onResume固定是1，
     * 所以还是需要通过StartActivityCount判断是由桌面返回的应用
     */
    public static int ResumeActivityCount;
    // 在onCreate进行add   在onDestroy进行remove
    private static Stack<Activity> activityStack;
    private static ActivityUtils instance;
    public static boolean hadStartMainActivity;

    private ActivityUtils() {
        activityStack = new Stack<>();
    }

    public static ActivityUtils getActivityUtils() {
        if (null == instance) {
            instance = new ActivityUtils();
        }
        return instance;
    }

    public static NotificationManager getNotificationManager(Context context) {
        return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    }

    /**
     * 添加Activity到堆栈
     */
    public void addActivity(Activity activity) {
        activityStack.add(activity);
    }

    /**
     * 获取当前Activity并且是还未finish的
     */
    public Activity currentActivity() {
        if (activityStack.isEmpty()) return null;
        Activity activity = activityStack.lastElement();
        if (activity.isFinishing() && activityStack.size() > 1) {
            activity = activityStack.elementAt(activityStack.size() - 2);
        }
        return activity;
    }

    public void removeActivity(Activity activity) {
        if (null != activity)
            activityStack.remove(activity);
    }

    /**
     * 结束所有Activity
     */
    public void finishAllActivity() {
        try {
            for (int i = activityStack.size() - 1; i >= 0; i--) {
                if (null != activityStack.get(i) && !activityStack.get(i).isFinishing()) {
                    activityStack.get(i).finish();
                }
            }
            activityStack.clear();
        } catch (Exception e) {
            L.e(e);
        }
    }

    /**
     * 退出应用程序
     */
    public void appExit(Context context) {
        if (context == null) return;
        try {
            getNotificationManager(context).cancelAll(); //退出应用程序取消所有状态栏消息
            finishAllActivity();
            ActivityManager activityMgr = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
            activityMgr.killBackgroundProcesses(context.getPackageName());
            System.exit(0);
        } catch (Exception ignored) {
        }
    }

    public Stack<Activity> getActivityStack() {
        return activityStack;
    }

    //复制文本
    public static void copyContentString(Context context, String content) {
        copyContentString(context, content, true);
    }

    public static void copyContentString(Context context, String content, boolean showToast) {
        ClipboardManager copy = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
        ClipData clearData = ClipData.newPlainText("", "");  //清除剪贴板之前的内容
        ClipData data = ClipData.newPlainText(content, content);
        if (copy != null) {
            copy.setPrimaryClip(clearData);
            copy.setPrimaryClip(data);
        }
        if (showToast)
            ToastUtils.showShort(context, R.string.base_copy_success);
    }

    //获取粘贴板文本，注：需要等待UI加载完之后才能正确获取到文本
    public static String getCopyContentString(Context context) {
        ClipboardManager copy = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
        if (copy != null) {
            ClipData data = copy.getPrimaryClip();
            if (data != null && data.getItemCount() > 0 && data.getItemAt(0) != null && data.getItemAt(0).getText() != null)
                return data.getItemAt(0).getText().toString();
        }
        return "";
    }

    // 如果输入法打开，则关闭
    public static void closeInputMethod(Activity context) {
        if (context == null) return;
        ThreadPoolUtils.getInstance().executeOnMainThread(() -> {
            try {
                View view = context.getCurrentFocus();
                if (view != null) {
                    InputMethodManager inputMethodManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
                    if (inputMethodManager != null && inputMethodManager.isActive()) { //输入法打开状态
                        inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(),
                                InputMethodManager.HIDE_NOT_ALWAYS);
                        view.clearFocus();
                    }
                }
            } catch (Exception e) {
                L.e(e);
            }
        });
    }

    public static void closeInputMethod(View view) {
        if (view == null) return;
        ThreadPoolUtils.getInstance().executeOnMainThread(() -> {
            try {
                InputMethodManager inputMethodManager = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
                if (inputMethodManager != null && inputMethodManager.isActive()) { //输入法打开状态
                    inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
                    view.clearFocus();
                }
            } catch (Exception e) {
                L.e(e);
            }
        });
    }

    // 如果输入法关闭，则打开
    // 因为立刻拉起软键盘，可能EditText还没获取焦点导致拉不起，所以进行延迟
    public static void openInputMethod(View focusView) {
        if (focusView == null) return;
        ThreadPoolUtils.getInstance().executeOnMainThread(() -> {
            focusView.requestFocus();
            focusView.postDelayed(() -> {
                try {
                    // WebView需要使用requestFocusFromTouch()才能拉起软键盘，但是会导致光标移动到最前面
                    InputMethodManager imm = (InputMethodManager) focusView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
                    if (imm != null)
                        imm.showSoftInput(focusView, InputMethodManager.SHOW_IMPLICIT);
                } catch (Exception e) {
                    L.e(e);
                }
            }, 50);
        });
    }

    /**
     * 禁止键盘弹出
     */
    public static void disableKeyboard(Activity activity) {
        activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
    }

    /**
     * 取消禁止键盘弹出
     */
    public static void enableKeyboard(Activity activity) {
        activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
    }

    // 是否是小屏/分屏模式
    public static boolean isInMultiWindowMode(Context context) {
        if (RomUtils.isOppo())
            return isInMultiWindowModeCheckOppo(context);
        else {
            boolean isInMultiWindowMode = false;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                if (context instanceof Activity) {
                    return ((Activity) context).isInMultiWindowMode();
                }
            }
            return false;
        }
    }

    private static boolean isInMultiWindowModeCheckOppo(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            ///获取App界面宽高
            WindowManager localWindowManager =
                    (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            WindowMetrics currentWindowMetrics = localWindowManager.getCurrentWindowMetrics();
            int height = currentWindowMetrics.getBounds().height();
            int width = currentWindowMetrics.getBounds().width();
            L.i("app check window width: " + width + " height: " + height);
            ///获取屏幕宽高
            Display display = context.getDisplay();
            int physicalHeight = display.getMode().getPhysicalHeight();
            int physicalWidth = display.getMode().getPhysicalWidth();
            L.i("app check window physicalWidth: " + physicalWidth + " physicalWidth: " + physicalHeight);
            return width != physicalWidth || height != physicalHeight;
        }
        return false;
    }

    /**
     * Android8.0对通知进行了管理，需要注册通知渠道，将会显示在系统应用信息界面上
     *
     * @param id   通知id，发送通知时使用对应id进行发送
     * @param name 通知渠道名称，将在系统应用信息界面上显示包含的通知
     *             例如："聊天通知"
     */
    @TargetApi(Build.VERSION_CODES.O)
    public static void registerNotification(Context context, String id, CharSequence name) {
        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        if (notificationManager == null) return;
        NotificationChannel channel1 = new NotificationChannel(id, name, NotificationManager.IMPORTANCE_HIGH);
        channel1.enableLights(true); //设置通知出现时的闪灯（如果 android 设备支持的话）
        channel1.setLightColor(Color.GREEN); //闪灯颜色
        channel1.enableVibration(true);// 设置通知出现时的震动（如果 android 设备支持的话）
//            channel1.setShowBadge(true); //是否在久按桌面图标时显示此渠道的通知，默认为true
        notificationManager.createNotificationChannel(channel1);
    }

    /**
     * 发送通知
     *
     * @param context        上下文对象
     * @param id             Android8.0以上需要的通知id，对应的是某个id 的通知渠道
     * @param title          标题
     * @param content        内容文本
     * @param intent         点击意图
     * @param notificationId 通知id，对应的是某类通知，id 相同的通知将会在通知栏进行覆盖
     */
    public static void sendNotification(Context context, String id, String title, String content, Intent intent, int notificationId) {
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); //会清除跳转目标activity及之上的所有activity
        Intent clickIntent = new Intent(context, NotificationClickReceiver.class);
        clickIntent.putExtra("intent", intent);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
            sendNotificationAbove26(context, id, title, content, clickIntent, notificationId);
        else
            sendNotificationBelow26(context, id, title, content, clickIntent, notificationId);
    }

    private static long PRE_SHOW_NOTIFICATION_TIME;

    private static void sendNotificationBelow26(Context context, String id, String title, String content, Intent clickIntent, int notificationId) {
        long curTime = System.currentTimeMillis();
        boolean needSound = curTime - PRE_SHOW_NOTIFICATION_TIME > 1000;
        PRE_SHOW_NOTIFICATION_TIME = curTime;
        NotificationCompat.Builder builder = new NotificationCompat.Builder(context, id);
        builder.setAutoCancel(true)//点击后让通知将消失
                .setContentTitle(title)
                .setContentText(content)
                .setTicker(title + '-' + content)
                //.setNumber(sendId)
                .setWhen(System.currentTimeMillis())//通知产生的时间，会在通知信息里显示
                .setPriority(Notification.PRIORITY_HIGH)//设置该通知优先级，高优先级才会显示横幅（即刚接收到信息时的悬浮弹窗）
                .setOngoing(false)//true，设置他为一个正在进行的通知。他们通常是用来表示一个后台任务,用户积极参与(如播放音乐)或以某种方式正在等待,因此占用设备(如一个文件下载,同步操作,主动网络连接)
                //向通知添加声音、闪灯和振动效果的最简单、最一致的方式是使用当前的用户默认设置，使用defaults属性，可以组合：  requires VIBRATE permission
                .setDefaults(needSound ? Notification.DEFAULT_ALL : Notification.DEFAULT_LIGHTS)
                .setSmallIcon(R.mipmap.logo);
        //.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.nlargelogo));
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, notificationId, clickIntent,
                PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
        builder.setContentIntent(pendingIntent);
        ((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE)).notify(notificationId, builder.build());
    }

    @TargetApi(Build.VERSION_CODES.O)
    private static void sendNotificationAbove26(Context context, String id, String title, String content, Intent clickIntent, int notificationId) {
        Notification.Builder builder = new Notification.Builder(context, id);
        //icon title text必须包含，不然影响桌面图标小红点的展示
        builder.setAutoCancel(true)//点击后让通知将消失
                .setContentTitle(title)
                .setContentText(content)
                .setTicker(title + '-' + content)
                .setWhen(System.currentTimeMillis())//通知产生的时间，会在通知信息里显示
                .setPriority(Notification.PRIORITY_HIGH)//设置该通知优先级，高优先级才会显示横幅（即刚接收到信息时的悬浮弹窗）
                .setOngoing(false)//true，设置他为一个正在进行的通知。他们通常是用来表示一个后台任务,用户积极参与(如播放音乐)或以某种方式正在等待,因此占用设备(如一个文件下载,同步操作,主动网络连接)
//                .setNumber(2) //长按桌面图标时显示的通知的数量
                //向通知添加声音、闪灯和振动效果的最简单、最一致的方式是使用当前的用户默认设置，使用defaults属性，可以组合：  requires VIBRATE permission
//                .setDefaults(needSound ? Notification.DEFAULT_ALL : Notification.DEFAULT_LIGHTS)
                .setSmallIcon(R.mipmap.logo);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, notificationId, clickIntent,
                PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
        builder.setContentIntent(pendingIntent);
        ((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE)).notify(notificationId, builder.build());
    }

    public static ActivityResultLauncher<Intent> startActivityForResult(ComponentActivity activity, ActivityResultCallback<ActivityResult> callback) {
        return activity.registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), callback);
    }
}
